<template>
  <!-- 面包屑导航区域 -->
  <div>
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>用户管理</el-breadcrumb-item>
      <el-breadcrumb-item>用户列表</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片面板 -->
    <el-card>
      <!-- 头部的input输入框部分 -->
      <el-row :gutter="20">
        <el-col :span="8">
          <el-input placeholder="请输入内容" v-model="queryData.query" clearable @clear="getUserList">
            <el-button slot="append" icon="el-icon-search" @click="checkedUserInfo"></el-button>
          </el-input>
        </el-col>
        <el-col :span="4">
          <el-button type="primary" @click="addUsersDialog">添加用户</el-button>
        </el-col>
      </el-row>
      <!-- 下面的表格区域 -->
      <el-table :data="userList" :border="true" :stripe="true">
        <!-- 为表格添加索引列 -->
        <el-table-column type="index"></el-table-column>
        <el-table-column prop="username" label="姓名" width="180"></el-table-column>
        <el-table-column prop="email" label="邮箱" width="180"></el-table-column>
        <el-table-column prop="mobile" label="电话"></el-table-column>
        <el-table-column prop="role_name" label="角色"></el-table-column>
        <el-table-column prop="mg_state" label="状态">
          <!-- 这里需要使用作用域插槽  具体可以看笔记  项目第8天 -->
          <template slot-scope="scope">
            <!-- 下面的这个东西可以拿到这一行的所有信息 -->
            <!-- {{scope.row}} -->
            <el-switch v-model="scope.row.mg_state" @change="changedStatus(scope.row)"></el-switch>
          </template>
        </el-table-column>
        <el-table-column prop="mg_state" label="操作">
          <!-- 这里又是表格嵌套其他的组件，所以还是用作用域插槽的方法 -->
          <template slot-scope="scope">
            <!-- 编辑的按钮 -->
            <el-button
              type="primary"
              icon="el-icon-edit"
              size="mini"
              @click="usersEdit(scope.row.id)"
            ></el-button>
            <!-- 删除的按钮 -->
            <el-button
              type="danger"
              icon="el-icon-delete"
              size="mini"
              @click="usersDelete(scope.row.id)"
            ></el-button>
            <!-- 这里使用的是文字提示，只在第三个上面提示 -->
            <el-tooltip
              class="item"
              effect="dark"
              content="分配权限"
              placement="top-end"
              :enterable="false"
            >
              <el-button
                type="warning"
                icon="el-icon-setting"
                size="mini"
                @click="setRoleRight(scope.row)"
              ></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <!-- 这是分页的模块 -->
      <el-pagination
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="queryData.pagenum"
        :page-sizes="[1, 2, 5, 10]"
        :page-size="queryData.pagesize"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      ></el-pagination>
    </el-card>
    <!-- 这是添加用户的弹出对话框 -->
    <el-dialog title="提示" :visible.sync="dialogFormVisible" width="50%" @close="addDialogClosed">
      <!-- 主体区域 -->
      <el-form :model="addForm" :rules="addUsersRules" ref="addFormRef" label-width="70px">
        <!-- 用户名 -->
        <el-form-item label="用户名" prop="username">
          <el-input v-model="addForm.username"></el-input>
        </el-form-item>
        <!-- 密码 -->
        <el-form-item label="密码" prop="password">
          <el-input v-model="addForm.password"></el-input>
        </el-form-item>
        <!-- 邮箱 -->
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="addForm.email"></el-input>
        </el-form-item>
        <!-- 电话 -->
        <el-form-item label="电话" prop="mobile">
          <el-input v-model="addForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- 底部区域 -->
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="beforeOfAddRules">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 这是编辑用户信息的弹出对话框 -->
    <el-dialog title="提示" :visible.sync="dialogEditVisible" width="50%" @close="editDialogClosed">
      <!-- 主体区域 -->
      <el-form ref="editFormRef" :model="editForm" :rules="editFormRules">
        <!-- 用户名部分 -->
        <el-form-item label="用户名">
          <el-input v-model="editForm.username" disabled></el-input>
        </el-form-item>
        <!-- 邮箱部分 -->
        <el-form-item label="邮箱" prop="email">
          <el-input v-model="editForm.email"></el-input>
        </el-form-item>
        <!-- 手机部分 -->
        <el-form-item label="电话" prop="mobile">
          <el-input v-model="editForm.mobile"></el-input>
        </el-form-item>
      </el-form>
      <!-- 这是底部区域 -->
      <div slot="footer" class="dialog-footer">
        <el-button @click=" dialogEditVisible= false">取 消</el-button>
        <el-button type="primary" @click="beforeOfEditRules">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 这是更新用户角色的会话框 -->
    <el-dialog title="分配角色" :visible.sync="dialogRolesVisible" width="50%">
      <div>
        <p>当前的用户:{{userInfo.username}}</p>
        <p>当前的角色:{{userInfo.role_name}}</p>
        <p>
          分配新角色:
          <el-select v-model="selectRoleId" placeholder="请选择">
            <el-option
              v-for="item in selectList"
              :key="item.id"
              :label="item.roleName"
              :value="item.id"
            ></el-option>
          </el-select>
        </p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogRolesVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveRoleInfo">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data: function () {
    // 自定义邮箱的验证
    const checkedEmail = (rule, value, callback) => {
      // value是要验证的值
      // rule是验证的规则，这里一般不使用
      // callback是一个回调函数
      // 定义验证邮箱的正则表达式
      const regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
      if (!regEmail.test(value)) {
        return callback(new Error("请输入正确的邮箱格式!"));
      }
      // 如果正确直接执行这个回调函数
      callback();
    };
    // 自定义电话的验证规则
    const checkedMobile = (rule, value, callback) => {
      //  定义验证电话的正则
      const regMobile = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
      if (!regMobile.test(value)) {
        return callback(new Error("请输入正确的电话格式!"));
      }
      // 如果正确则直接执行回调
      callback();
    };
    return {
      //这里是发起获取用户列表时，所携带的参数
      queryData: {
        query: "",
        pagenum: 1,
        pagesize: 2,
      },
      //接收返回的数据,注意和element ui 里面的格式保持一致  这是一个数组
      userList: [],
      //接收返回的总记录数
      total: 0,
      // 这是控制添加用户对话框的显示与隐藏
      dialogFormVisible: false,
      // 这是绑定在对话框上的表单model绑定属性
      addForm: {
        username: "",
        password: "",
        email: "",
        mobile: "",
      },
      // 这是添加用户对话框的表单验证
      addUsersRules: {
        // 用户名的验证
        username: [
          { required: true, message: "请输入用户名", trigger: "blur" },
          {
            min: 3,
            max: 10,
            message: "长度在 3 到 10 个字符",
            trigger: "blur",
          },
        ],
        // 这是密码的验证的规则
        password: [
          { required: true, message: "请输入密码", trigger: "blur" },
          {
            min: 6,
            max: 15,
            message: "长度在 6 到 15 个字符",
            trigger: "blur",
          },
        ],
        // 这是邮箱的验证规则
        email: [
          { required: true, message: "请输入邮箱", trigger: "blur" },
          { validator: checkedEmail, trigger: "blur" },
        ],
        // 这是电话的验证规则
        mobile: [
          { required: true, message: "请输入电话", trigger: "blur" },
          { validator: checkedMobile, trigger: "blur" },
        ],
      },
      // 这是控制编辑用户对话框的显示与隐藏
      dialogEditVisible: false,
      // 这是绑定在编辑弹出框表单的数据
      editForm: {
        username: "",
        email: "",
        mobile: "",
      },
      // 这是编辑弹出框的表单验证,用户名不用验证了,直接验证邮箱和电话
      editFormRules: {
        // 邮箱的验证
        email: [
          { required: true, message: "请输入邮箱", trigger: "blur" },
          { validator: checkedEmail, trigger: "blur" },
        ],
        // 电话的验证规则
        mobile: [
          { required: true, message: "请输入电话", trigger: "blur" },
          { validator: checkedMobile, trigger: "blur" },
        ],
      },
      // 这是控制更新角色对话框的显示与隐藏
      dialogRolesVisible: false,
      // 用户的数据
      userInfo: {},
      // 这是全部角色的数据
      selectList: [],
      // 用户选择后,最终呈现的角色 当用户选中某个角色 把这个觉得的id给selectRoleId
      selectRoleId: "",
    };
  },
  methods: {
    //   这里定义的是获取用户列表的函数，在生命周期函数 created中生效
    getUserList: async function () {
      // 调用接口
      const { data: result } = await this.$http.get("users", {
        params: this.queryData,
      }); //注意get请求时的携带参数的格式
      if (result.meta.status !== 200)
        return this.$message.error("获取用户列表失败!");
      this.userList = result.data.users;
      this.total = result.data.total;
      // console.log(this.userList);
    },
    // 这里监听pagesize的变化的函数
    handleSizeChange: function (pagesize) {
      // 把改变后的每页显示的条数，重新赋值给queryData里面的pagesize
      this.queryData.pagesize = pagesize;
      // 重新获取用户的列表
      this.getUserList();
    },
    // 这是监听pagenum变化的函数
    handleCurrentChange: function (pagenum) {
      //把改变的pagenum数 重新赋值给queryData里面的pagenum
      this.queryData.pagenum = pagenum;
      //重新获取用户的列表
      this.getUserList();
    },
    // 这里是监听用户状态的改变处理函数,把改变的状态值,发起put请求修改后，在重新获取用户的列表
    changedStatus: async function (userinfo) {
      // 发起修改状态的请求
      const { data: result } = await this.$http.put(
        `users/${userinfo.id}/state/${userinfo.mg_state}`
      );
      console.log(result);
      if (result.meta.status !== 200) {
        // 如果修改状态失败，则把用户的状态还原为初始值
        userinfo.mg_state = !userinfo.mg_state;
        return this.$message.error("修改用户状态失败!");
      }
      this.$message.success("修改用户状态成功!");
      // 在重新获取一下用户列表
      this.getUserList();
    },
    // 这是实现搜索查询功能的处理函数
    checkedUserInfo: function () {
      // 在这里重新获取用户列表
      this.getUserList();
    },
    // 这是点击添加按钮的添加用户的对话框的处理函数
    addUsersDialog: function () {
      this.dialogFormVisible = true;
    },
    //这是添加用户对话框的重置功能的相关处理函数
    addDialogClosed: function () {
      this.$refs.addFormRef.resetFields();
    },
    // 对添加用户信息预验证功能的相关处理函数
    beforeOfAddRules: function () {
      let that = this;
      that.$refs.addFormRef.validate(async function (valid) {
        // 当预验证通过的时候,即是valid返回的是true时候,调用添加用户的接口
        if (valid) {
          const { data: result } = await that.$http.post("users", that.addForm);
          console.log(result);
          // 重新获取用户列表
          that.getUserList();
          // 关闭弹出框
          that.dialogFormVisible = false;
        }
      });
    },
    // 这是点击编辑按钮的编辑用户的对话框的处理函数
    usersEdit: async function (id) {
      this.dialogEditVisible = true;
      // 拿到每行数据的id值,然后发起根据id查询用户信息的请求得到数据，在渲染到表单中
      const { data: result } = await this.$http.get("/users/" + id);
      if (result.meta.status !== 200)
        return this.$message.error(result.meta.msg);
      // 查询成功的提示消息
      this.$message.success(result.meta.msg);
      // 接下来是把查询的数据。赋值到编辑弹出框的表单里面
      this.editForm = result.data;
    },

    // 这是监听编辑弹出对话框关闭时的 相关重置功能
    editDialogClosed: function () {
      this.$refs.editFormRef.resetFields();
    },
    // 编辑用户弹出框的预校验功能的处理函数
    beforeOfEditRules: function () {
      let that = this;
      that.$refs.editFormRef.validate(async function (valid) {
        // 如果预验证的结果为true则说明验证通过，则调用编辑用户数据的接口
        // 注意这里的id是从editForm里面获取的,因为上一步操作已经完成了赋值的操作
        if (valid) {
          // 发起接口的请求
          const { data: result } = await that.$http.put(
            "users/" + that.editForm.id,
            {
              email: that.editForm.email,
              mobile: that.editForm.mobile,
            }
          );
          if (result.meta.status !== 200)
            return that.$message.error(result.meta.msg);
          // 修改正确的提示信息
          that.$message.success(result.meta.msg);
          // 请求完毕，再把对话框隐藏 同时重新获取用户列表
          that.getUserList();
          that.dialogEditVisible = false;
          console.log(result);
        }
      });
    },
    // 点击删除按钮的相关操作的处理函数
    usersDelete: async function (id) {
      // 点击之后的弹出的弹出框
      const result = await this.$prompt(
        "此操作将永久删除该用户,是否继续?",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
          // 如果点击了取消将会抛出错误异常,因此要调用catch来捕获错误 因为返回的是一个promise对象  因此要使用async await
        }
      ).catch(function (error) {
        return error;
      });
      // 当result返回的是cancel时,就是取消删除了 ,然后设置一个提示框
      if (result === "cancel") {
        return this.$message({
          type: "info",
          message: "取消删除",
        });
      }
      // 当为confirm,则监听到确实点击了删除按钮,这时调用删除的接口请求
      const { data: res } = await this.$http.delete("users/" + id);
      if (res.meta.status !== 200) return this.$message.error("删除失败!");
      // 如果请求成功,则重新获取用户列表
      this.$message.success(res.meta.msg);
      this.getUserList();
    },
    // 这是用户更新角色的相关处理函数 分配权限
    setRoleRight: async function (info) {
      // 调接口,获取全部的角色列表,同时完成赋值的操作
      const { data: result } = await this.$http.get("roles");
      if (result.meta.status !== 200)
        return this.$message.error("获取角色列表失败!");
      // 成功的提示信息
      this.$message.success(result.meta.msg);
      // 关闭会话框
      this.dialogRolesVisible = true;
      // 完成赋值操作
      this.userInfo = info; //用户信息
      this.selectList = result.data; //角色的信息
      // console.log(info);
    },
    // 点击确定按钮的确认更新角色操作
    saveRoleInfo: async function () {
      // 调接口
      if (!this.selectRoleId) {
        return this.$message.error("请选择角色!");
      }
      const { data: result } = await this.$http.put(
        `users/${this.userInfo.id}/role`,
        {
          rid: this.selectRoleId,
        }
      );
      if (result.meta.status !== 200)
        return this.$message.error("设置角色失败!");
      this.$message.success(result.meta.msg);
      // 重新获取用户列表  并且关闭会话框
      this.getUserList();
      this.dialogRolesVisible = false;
    },
  },
  //   生命周期函数
  created: function () {
    //   当页面加载的时候,就调用这个函数 来获取用户的列表
    this.getUserList();
  },
};
</script>

<style lang="less" scoped></style>